from lxml import etree


"""
 示例1 按序选择
 我们在选择的时候某些属性可能同时匹配了多个节点,  利用中括号传入索引的方法获取特定次序的节点
 注意，这里和代码中不同，序号是以 1 开头的，不是以 0 开头
 
 这里我们使用了 last、position 等方法。在 XPath 中，提供了 100 多个方法，包括存取、数值、字符串、逻辑、节点、序列等处理功能，它们的具体作用可以参考：http://www.w3school.com.cn/xpath/xpath_functions.asp。
"""

text = '''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a>
     </ul>
 </div>
'''
html = etree.HTML(text)
result = html.xpath('//li[1]/a/text()') # ['first item']
print(result)
result = html.xpath('//li[last()]/a/text()') # ['fifth item']
print(result)
result = html.xpath('//li[position()<3]/a/text()')  # ['first item', 'second item']  选取了位置小于 3 的 li 节点，也就是位置序号为 1 和 2 的节点，得到的结果就是前两个 li 节点
print(result)
result = html.xpath('//li[last()-2]/a/text()') # ['third item'] 选取了倒数第三个 li 节点，中括号中调用 last 方法再减去 2 即可
print(result)


"""
 示例2 节点轴选择
 XPath 提供了很多节点轴选择方法，包括获取子元素、兄弟元素、父元素、祖先元素等
"""



text = '''
<div>
    <ul>
         <li class="item-0"><a href="link1.html"><span>first item</span></a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a>
     </ul>
 </div>
'''

"""
解析如下:  
第一次选择时，我们调用了 ancestor 轴，可以获取所有祖先节点。其后需要跟两个冒号，然后是节点的选择器，这里我们直接使用 *，表示匹配所有节点，因此返回结果是第一个 li 节点的所有祖先节点，包括 html、body、div 和 ul。

第二次选择时，我们又加了限定条件，这次在冒号后面加了 div，这样得到的结果就只有 div 这个祖先节点了。

第三次选择时，我们调用了 attribute 轴，可以获取所有属性值，其后跟的选择器还是 *，这代表获取节点的所有属性，返回值就是 li 节点的所有属性值。

第四次选择时，我们调用了 child 轴，可以获取所有直接子节点。这里我们又加了限定条件，选取 href 属性为 link1.html 的 a 节点。

第五次选择时，我们调用了 descendant 轴，可以获取所有子孙节点。这里我们又加了限定条件获取 span 节点，所以返回的结果只包含 span 节点而不包含 a 节点。

第六次选择时，我们调用了 following 轴，可以获取当前节点之后的所有节点。这里我们虽然使用的是 * 匹配，但又加了索引选择，所以只获取了第二个后续节点。

第七次选择时，我们调用了 following-sibling 轴，可以获取当前节点之后的所有同级节点。这里我们使用 * 匹配，所以获取了所有后续同级节点。

以上是 XPath 轴的简单用法，更多轴的用法可以参考：http://www.w3school.com.cn/xpath/xpath_axes.asp。
"""

html = etree.HTML(text)
result = html.xpath('//li[1]/ancestor::*')
print(result)
result = html.xpath('//li[1]/ancestor::div')
print(result)
result = html.xpath('//li[1]/attribute::*')
print(result)
result = html.xpath('//li[1]/child::a[@href="link1.html"]')
print(result)
result = html.xpath('//li[1]/descendant::span')
print(result)
result = html.xpath('//li[1]/following::*[2]')
print(result)
result = html.xpath('//li[1]/following-sibling::*')
print(result)

